package com.sias.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;

import javax.swing.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * @author 吴文杰
 * @version 1.0
 * @since 2023/6/22 13:53
 */
@Configuration
public class BootApplication {
  public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
    // 1.演示获取BeanDefinition源
    SpringApplication springApplication = new SpringApplication(BootApplication.class);

    HashSet<String> set = new HashSet<>();
    set.add("classpath:b01.xml");
    springApplication.setSources(set);
    // 2.演示推断应用类型
    Method deduceFromClasspath = WebApplicationType.class.getDeclaredMethod("deduceFromClasspath");
    deduceFromClasspath.setAccessible(true);
    System.out.println("应用类型为："+deduceFromClasspath.invoke(null));;

    // 3.演示ApplicationContext初始化器
    springApplication.addInitializers(applicationContext -> {
      if (applicationContext instanceof GenericApplicationContext){
        GenericApplicationContext gec = (GenericApplicationContext)applicationContext;
        gec.registerBean("bean3", Bean3.class);
      }
    });

    // 4.演示监听器与事件
    springApplication.addListeners(event -> System.out.println("\t事件为："+event.getClass()));

    // 5.演示主类推断
    Method deduceMainApplicationClass = SpringApplication.class.getDeclaredMethod("deduceMainApplicationClass");
    deduceMainApplicationClass.setAccessible(true);
    System.out.println("主类是："+deduceMainApplicationClass.invoke(springApplication));;

    ConfigurableApplicationContext context = springApplication.run(args);
    // 创建 ApplicationContext
    // 调用初始化器 对ApplicationContext做扩展
    // ApplicationContext.refresh

    for (String name : context.getBeanDefinitionNames()) {
      System.out.println("name="+name+"\t\t来源："+context.getBeanFactory().getBeanDefinition(name).getResourceDescription());
    }

    context.close();
  }


  static class Bean1{
    public Bean1() {
    }
  }
  static class Bean2{
    public Bean2() {
    }
  }
  static class Bean3{
    public Bean3() {
    }
  }

  @Bean
  public Bean2 bean2(){
    return new Bean2();
  }

  @Bean
  public TomcatServletWebServerFactory tomcatServletWebServerFactory(){
    return new TomcatServletWebServerFactory();
  }
}
